package com.moran.controller;

import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.moran.domain.WeatherInfo;
import com.moran.util.CommonUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.ai.chat.ChatClient;
import org.springframework.ai.chat.StreamingChatClient;
import org.springframework.ai.chat.messages.AssistantMessage;
import org.springframework.ai.chat.messages.SystemMessage;
import org.springframework.ai.chat.messages.UserMessage;
import org.springframework.ai.chat.prompt.Prompt;
import org.springframework.ai.chat.prompt.PromptTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import reactor.core.publisher.Flux;

import java.util.Arrays;

@Slf4j
@RestController
@RequestMapping("/v0.8.1")
public class ChatClientController {

    @Autowired
    private ChatClient chatClient;

    @Autowired
    private StreamingChatClient streamingChatClient;

    @Autowired
    private CommonUtil commonUtil;

    /**
     * 当前用户输入后，返回文本类型的回答
     * @return
     */
    @PostMapping("/chat")
    public String chat(@RequestParam("userInput")  String userInput) {
        return chatClient.call(userInput);
    }

    /**
     * 使用系统提示进行聊天。
     * @param userInput 用户输入的消息
     * @return AI 的回复
     */
    @PostMapping("/chatWithPromt")
    public String chatWithPromt(@RequestParam("userInput") String userInput) {
        // 创建系统提示词
        SystemMessage systemMessage = new SystemMessage("你是一个java领域的专家。");
        // 创建用户消息
        UserMessage userMessage = new UserMessage(userInput);
        // 构建Prompt对象，包含系统消息和用户消息
        Prompt prompt = new Prompt(Arrays.asList(systemMessage, userMessage));
        // 调用ChatClient的generate方法
        AssistantMessage assistantMessage = chatClient.call(prompt).getResult().getOutput();
        // 返回助手的响应
        return assistantMessage.getContent();
    }

    /**
     * 使用流式提示和流式客户端与 DeepSeek 进行聊天。
     * @param userInput 用户输入的消息
     * @return 返回一个 Flux<String>，代表流式生成的回复片段
     * curl -X POST http://localhost:9166/v0.8.1/chatWithStream -d "userInput=spring原理"
     */
    @PostMapping(value = "/chatWithStream", produces = "text/event-stream")
    public Flux<String> chatWithStream(@RequestParam("userInput") String userInput) {
        // 创建系统提示词
        SystemMessage systemMessage = new SystemMessage("你是一个java领域的专家。");
        // 创建用户消息
        UserMessage userMessage = new UserMessage(userInput);
        // 构建Prompt对象，包含系统消息和用户消息
        Prompt prompt = new Prompt(Arrays.asList(systemMessage, userMessage));

        // 调用 chatClient.stream() 方法，返回一个 Flux<ChatResponse> 流
        // 对 Flux 流进行处理：
        return streamingChatClient.stream(prompt)
                // 从每个 ChatResponse 中提取出内容 delta (即本次流式返回的增量内容)
                .map(chatResponse -> {
                    String content = chatResponse.getResult().getOutput().getContent();
                    log.info(content);
                    return content;
                })
                // 处理过程中可能出现的错误
                .onErrorResume(throwable -> Flux.just("流式响应出现错误: " + throwable.getMessage()));
    }

    /**
     * 根据大模型返回消息封装实体对象
     */
    @PostMapping("/getWeatherInfoWithTemplate")
    public WeatherInfo getWeatherInfoWithTemplate(@RequestParam("city") String city) {
        // 提示词
        String template = """
            你是一个专业的天气信息助手。
            请根据用户提供的城市名称，查询并返回详细的天气信息。
            你必须以严格的 JSON 格式返回，JSON 的结构必须完全匹配以下 Java Record 的定义：
            {weatherInfoSchema}

            城市: {city}
            """;

        // PromptTemplate 会自动将 weatherInfoSchema 替换为 WeatherInfo 类的 JSON Schema
        PromptTemplate promptTemplate = new PromptTemplate(template);
        promptTemplate.add("city", city);
        // ✅ 这行代码会自动生成 WeatherInfo 类的 JSON Schema
        promptTemplate.add("weatherInfoSchema", commonUtil.getJsonSchema(WeatherInfo.class));

        Prompt prompt = promptTemplate.create();

        String response = chatClient.call(prompt).getResult().getOutput().getContent();
        response = StrUtil.replace(response, "```json", "");
        response = StrUtil.replace(response, "```", "");
        log.info("模型响应结果为：{}", response);
        return JSONUtil.toBean(response, WeatherInfo.class);
    }

}
